/**
 * Copyright (c) Niels Tiben (nielstiben@outlook.com)
 */
package nl.saxion.nena.opentcs.commadapter.ros2.control_center.control_panel.gui_components;

import lombok.AllArgsConstructor;
import nl.saxion.nena.opentcs.commadapter.ros2.control_center.control_panel.library.InputValidationLib;
import nl.saxion.nena.opentcs.commadapter.ros2.kernel.vehicle_adapter.communication.Node;

import javax.swing.text.Document;

/**
 * Instruct the kernel to use the given namespace when a {@link Node} is initiated.
 *
 * @author Niels Tiben
 */
public final class CoordinateInputPanel extends TextInputPanel {
    private boolean isXInputFieldValid = true;
    private boolean isYInputFieldValid = true;
    private boolean isZInputFieldValid = true;

    private CoordinateInputPanel(String panelTitle) {
        super(panelTitle);
        initComponents();
    }

    /**
     * Enable input validation against the {@link InputValidationLib#getIsDoubleRegex()} regular expression.
     */
    private void enableInputValidation() {
        String isDoubleRegex = InputValidationLib.getIsDoubleRegex();
        this.xInputField.getDocument().addDocumentListener(new TextInputValidator(isDoubleRegex));
        this.yInputField.getDocument().addDocumentListener(new TextInputValidator(isDoubleRegex));
        this.zInputField.getDocument().addDocumentListener(new TextInputValidator(isDoubleRegex));
    }

    @Override
    protected void captureInput() {
        this.input = new String[]{
                this.xInputField.getText(),
                this.yInputField.getText(),
                this.zInputField.getText()
        };
    }

    /**
     * Mark the document as valid, but only if all three text input field match the criteria of a valid coordinate.
     *
     * @param valid Whether the document is valid.
     * @param doc   The document
     */
    @Override
    protected void setInputValid(boolean valid, Document doc) {
        // Find out to which input field the document belongs and check the others
        boolean allValid = valid;
        if (doc == xInputField.getDocument()) {
            isXInputFieldValid = valid;
            if (!(isYInputFieldValid && isZInputFieldValid)) {
                allValid = false;
            }
        } else if (doc == yInputField.getDocument()) {
            isYInputFieldValid = valid;
            if (!(isXInputFieldValid && isZInputFieldValid)) {
                allValid = false;
            }
        } else if (doc == zInputField.getDocument()) {
            isZInputFieldValid = valid;
            if (!(isXInputFieldValid && isYInputFieldValid)) {
                allValid = false;
            }
        } else {
            allValid = false;
        }

        setInputValid(allValid);
    }

    // CHECKSTYLE:OFF

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        instructionLabel = new javax.swing.JLabel();
        xLabel = new javax.swing.JLabel();
        xInputField = new javax.swing.JTextField();
        xUnitLabel = new javax.swing.JLabel();
        yLabel = new javax.swing.JLabel();
        yInputField = new javax.swing.JTextField();
        yUnitLabel = new javax.swing.JLabel();
        zLabel = new javax.swing.JLabel();
        zInputField = new javax.swing.JTextField();
        zUnitLabel = new javax.swing.JLabel();

        setPreferredSize(new java.awt.Dimension(280, 150));
        setLayout(new java.awt.GridBagLayout());

        instructionLabel.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("nl/saxion/nena/opentcs/commadapter/ros2/Bundle"); // NOI18N
        instructionLabel.setText(bundle.getString("ros2CommAdapterPanel.dialog_dispatchVehicleToCoordinate.text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(instructionLabel, gridBagConstraints);

        xLabel.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        xLabel.setText("X");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(xLabel, gridBagConstraints);

        xInputField.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        xInputField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        xInputField.setText("initial_value");
        xInputField.setName("xInputField"); // NOI18N
        xInputField.setPreferredSize(new java.awt.Dimension(60, 30));
        xInputField.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                xInputFieldFocusGained(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(xInputField, gridBagConstraints);
        xInputField.getAccessibleContext().setAccessibleName("");

        xUnitLabel.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        xUnitLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        xUnitLabel.setText(bundle.getString("ros2CommAdapterPanel.unit_meter")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(xUnitLabel, gridBagConstraints);

        yLabel.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        yLabel.setText("Y");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(yLabel, gridBagConstraints);

        yInputField.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        yInputField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        yInputField.setText("initial_value");
        yInputField.setName("yInputField"); // NOI18N
        yInputField.setPreferredSize(new java.awt.Dimension(60, 30));
        yInputField.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                yInputFieldFocusGained(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(yInputField, gridBagConstraints);
        yInputField.getAccessibleContext().setAccessibleName("");

        yUnitLabel.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        yUnitLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        yUnitLabel.setText(bundle.getString("ros2CommAdapterPanel.unit_meter")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(yUnitLabel, gridBagConstraints);

        zLabel.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        zLabel.setText("Z");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(zLabel, gridBagConstraints);

        zInputField.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        zInputField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        zInputField.setText("initial_value");
        zInputField.setName("zInputField"); // NOI18N
        zInputField.setPreferredSize(new java.awt.Dimension(60, 30));
        zInputField.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                zInputFieldFocusGained(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(zInputField, gridBagConstraints);
        zInputField.getAccessibleContext().setAccessibleName("");

        zUnitLabel.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
        zUnitLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        zUnitLabel.setText(bundle.getString("ros2CommAdapterPanel.unit_meter")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(zUnitLabel, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents

    private void xInputFieldFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_xInputFieldFocusGained
        xInputField.selectAll();
    }//GEN-LAST:event_xInputFieldFocusGained

    private void yInputFieldFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_yInputFieldFocusGained
        yInputField.selectAll();
    }//GEN-LAST:event_yInputFieldFocusGained

    private void zInputFieldFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_zInputFieldFocusGained
        zInputField.selectAll();
    }//GEN-LAST:event_zInputFieldFocusGained

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel instructionLabel;
    private javax.swing.JTextField xInputField;
    private javax.swing.JLabel xLabel;
    private javax.swing.JLabel xUnitLabel;
    private javax.swing.JTextField yInputField;
    private javax.swing.JLabel yLabel;
    private javax.swing.JLabel yUnitLabel;
    private javax.swing.JTextField zInputField;
    private javax.swing.JLabel zLabel;
    private javax.swing.JLabel zUnitLabel;
    // End of variables declaration//GEN-END:variables
    //CHECKSTYLE:ON

    /**
     * See {@link InputPanel.Builder}.
     */
    @AllArgsConstructor
    public static class Builder implements InputPanel.Builder {
        private final String panelTitle;

        @Override
        public InputPanel build() {
            CoordinateInputPanel panel = new CoordinateInputPanel(panelTitle);
            panel.enableInputValidation();
            panel.xInputField.setText(null);
            panel.yInputField.setText(null);
            panel.zInputField.setText(null);
            return panel;
        }
    }
}
